package com.ysm.freestyle.utils

import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.text.TextUtils
import android.util.Log
import androidx.documentfile.provider.DocumentFile
import com.blankj.utilcode.util.ConvertUtils
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.TimeUtils
import com.blankj.utilcode.util.Utils
import com.ysm.freestyle.viewmodel.FileScanViewModel
import com.ysm.freestyle.viewmodel.PathTextViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.io.Serializable
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale

/**
 * 通用文件类型
 */
const val TYPE_ALL_TEXT = "ALL"
const val TYPE_IMAGE_TEXT = "Photo"
const val TYPE_VIDEO_TEXT = "Video"
const val TYPE_AUDIO_TEXT = "Audio"
const val TYPE_DOC_TEXT = "Doc"
const val TYPE_PDF_TEXT = "Pdf"
const val TYPE_PPT_TEXT = "Ppt"
const val TYPE_XLS_TEXT = "Xls"
const val TYPE_TXT_TEXT = "Txt"
const val TYPE_ALL_WENBEN_TEXT = "Documents"
const val TYPE_COMPRESS_TEXT = "Compress"

/**
 * 扫描过程标识
 */
const val SCAN_STATUS_SCANNING = 1                              //扫描过程中
const val SCAN_STATUS_SCAN_PATH = 2                             //正在扫描的路径
const val SCAN_STATUS_COMPLETE = 3                              //扫描完成

const val SCAN_TYPE_NORMAL = 1
const val SCAN_TYPE_DEEP = 2

/**
 * 使用协程来扫描手机内部所有文件，多协程并发处理
 */
class ScanFileNewUtil(
    val context: Context,
    private var fileScanViewModel: FileScanViewModel?,
    private var pathTextViewModel: PathTextViewModel?
) {
    //扫描文件任务量大，属于CPU密集型操作需使用Dispatchers.Default
    private val scope = CoroutineScope(Dispatchers.Default)
    private var mainJob: Job? = null

    /**
     * 从全部的手机文件进行搜索——普通扫描，不扫描data文件夹
     */
    suspend fun getAllFilesNormal(type: String) {
        mainJob = scope.launch {
            try {
                //扫描外部文件信息
                //只对外部文件夹扫描，把根目录各文件夹分协程并行扫描节省数倍时间
                val paramFile = Environment.getExternalStorageDirectory()
                if (paramFile == null || !FileUtils.isDir(paramFile)) return@launch
                val arrayOfFile = paramFile.listFiles()
                if (arrayOfFile != null && arrayOfFile.isNotEmpty()) {
                    val files = arrayOfFile.size
                    for (i in 0 until files) {
                        val file = arrayOfFile[i]
//                        Log.i("ScanFileNewUtil","file.absolutePath => ${file.absolutePath}")

                        if (file.isDirectory) {
                            //创建多少个子协程全看有多少主目录下有多少个文件夹，这些文件夹并行扫描
                            launch {
                                listFilesInDirWithFilterNew(file, type)
                            }
                        } else {
                            if (file.absolutePath.contains(context.packageName) || file.absolutePath.contains(
                                    "SugoilabFileRecovery"
                                )
                            ) {
                                continue
                            }
                            //判断并获取当前扫描的文件是否是对应类型文件
                          val fileEntity: FileEntity = findSingleFileUpdateUi(file, type) ?: continue
//                            val fileEntity: FileEntity = findSingleFileUpdateAllTypeUi(file, type) ?: continue

//                            Log.i("ScanFileNewUtil","file get  => ${fileEntity.newFileName}")

                            //文件获取成功提醒线程更新
                            fileScanViewModel?.setData(fileEntity)
                        }
                    }
                }
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
        }
        mainJob!!.join()
    }

    /**
     * 从全部的手机文件进行搜索——深度扫描
     */
    suspend fun getAllFilesDeep(type: String) {
        mainJob = scope.launch {
            try {
                //先扫描外部文件信息
                launch {
                    //深度扫描没必要把外部文件按文件夹分不同协程并行，因为内部Data文件夹扫描方式相比外部文件夹来说很慢，没必要额外占用多个协程处理
                    listFilesInDirWithFilterNew(Environment.getExternalStorageDirectory(), type)
                }
                //再扫描Android data文件夹信息，扫描方式不同
                val dirUri =
                    Uri.parse(
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                            "content://com.android.externalstorage.documents/tree/primary%3AA%E2%80%8Bndroid%2Fdata"
                        } else {
                            "content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata"
                        }
                    )
                val documentFile = DocumentFile.fromTreeUri(context, dirUri)
                //遍历DocumentFile，但是要避开本app的缓存目录
                val files = documentFile?.listFiles()
                files?.let {
                    for (file in files) {
                        if (file.uri.path?.contains(context.packageName) == true) {
                            continue
                        }
                        if (file.isDirectory)//如果是目录则重复本方法往目录下执行。
                        //创建多少个子协程全看有多少主目录下有多少个文件夹，这些文件夹并行扫描
                            launch {
                                getFileFromDirByDocumentFile(file, type)
                            }
                        else {//如果是文件则判断文件类型
                            try {
//                                val fileEntity = getSingleFileByDocumentFile(file, type) ?: continue
                                val fileEntity = getSingleFileByDocumentFileAllType(file, type) ?: continue

                                //文件获取成功提醒线程更新
                                fileScanViewModel?.setData(fileEntity)
                            } catch (e: Exception) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
        }
        mainJob!!.join()
    }

    private fun listFilesInDirWithFilterNew(
        paramFile: File?,
        type: String
    ) {
        if (paramFile == null || !FileUtils.isDir(paramFile)) return
        val arrayOfFile = paramFile.listFiles()
        if (arrayOfFile != null && arrayOfFile.isNotEmpty()) {
            val j = arrayOfFile.size
            for (i in 0 until j) {
                val file = arrayOfFile[i]
                //返回当前正在扫描的文件路径
                pathTextViewModel?.setData(file.absolutePath)

                if (file.isDirectory) {
                    listFilesInDirWithFilterNew(file, type)
                } else {
                    if (file.absolutePath.contains(context.packageName) || file.absolutePath.contains(
                            "SugoilabFileRecovery"
                        )
                    ) {
                        continue
                    }
                    //判断并获取当前扫描的文件是否是对应类型文件
                    val fileEntity: FileEntity = findSingleFileUpdateUi(file, type) ?: continue

//                    val fileEntity: FileEntity = findSingleFileUpdateAllTypeUi(file, type) ?: continue

//                    Log.i("ScanFileNewUtil","file get  => ${fileEntity.fileName}")
                    //文件获取成功提醒数据更新
                    fileScanViewModel?.setData(fileEntity)
                }
            }
        }
    }

    private fun findSingleFileUpdateUi(paramFile: File, type: String): FileEntity? {
        try {
            val fileEntity = FileEntity(UI_TYPE_MAIN)
            val filePathLowCase = paramFile.absolutePath.lowercase(Locale.getDefault())
            val fileType: String = CheckFileTypeUtil.getFileType(paramFile.absolutePath).toString()

            when (type) {
                TYPE_IMAGE_TEXT -> {
                    if (filePathLowCase.endsWith(".bmp") || filePathLowCase.endsWith(".jpg") || filePathLowCase.endsWith(
                            ".png"
                        ) || filePathLowCase.endsWith(
                            ".tif"
                        ) || filePathLowCase.endsWith(".gif") || filePathLowCase.endsWith(".webp") || fileType.equals(
                            "bmp",
                            ignoreCase = true
                        ) || fileType.equals("jpg", ignoreCase = true) || fileType.equals(
                            "png",
                            ignoreCase = true
                        ) || fileType.equals("tif", ignoreCase = true) || fileType.equals(
                            "gif",
                            ignoreCase = true
                        ) || fileType.equals("webp", ignoreCase = true)
                    ) {
                        fileEntity.fileClass = ItemClassType.PHOTOS
                    } else {
                        return null
                    }
                }

                TYPE_VIDEO_TEXT -> {
                    if (filePathLowCase.endsWith(".mp4") || filePathLowCase.endsWith(".avi") || filePathLowCase.endsWith(
                            ".3gp"
                        ) || filePathLowCase.endsWith(
                            ".wmv"
                        ) || filePathLowCase.endsWith(".flv") || filePathLowCase.endsWith(".rmvb") || filePathLowCase.endsWith(
                            ".mov"
                        )
                        || fileType.equals("flv", ignoreCase = true) || fileType.equals(
                            "wmv",
                            ignoreCase = true
                        ) || fileType.equals("3gp", ignoreCase = true) || fileType.equals(
                            "avi",
                            ignoreCase = true
                        ) || fileType.equals("mp4", ignoreCase = true) || fileType.equals(
                            "rmvb",
                            ignoreCase = true
                        ) || fileType.equals(
                            "mov",
                            ignoreCase = true
                        )
                    ) {
                        fileEntity.fileClass = ItemClassType.VIDEOS
                    } else {
                        return null
                    }
                }

                TYPE_AUDIO_TEXT -> {
                    if (filePathLowCase.endsWith(".mp3") || filePathLowCase.endsWith(".amr") || filePathLowCase.endsWith(
                            ".m4a"
                        ) || filePathLowCase.endsWith(
                            ".wav"
                        ) || filePathLowCase.endsWith(".aac") || filePathLowCase.endsWith(".ogg") || fileType.equals(
                            "mp3",
                            ignoreCase = true
                        ) || fileType.equals("amr", ignoreCase = true) || fileType.equals(
                            "m4a",
                            ignoreCase = true
                        ) || fileType.equals("wav", ignoreCase = true) || fileType.equals(
                            "aac",
                            ignoreCase = true
                        ) || fileType.equals("ogg", ignoreCase = true)
                    ) {
                        fileEntity.fileClass = ItemClassType.MUSIC
                    } else {
                        return null
                    }
                }

                TYPE_DOC_TEXT -> {
                    if (filePathLowCase.endsWith(".doc") || filePathLowCase.endsWith(".docx")) {
                    } else {
                        return null
                    }
                }

                TYPE_PDF_TEXT -> {
                    if (filePathLowCase.endsWith(".pdf")) {
                    } else {
                        return null
                    }
                }

                TYPE_XLS_TEXT -> {
                    if (filePathLowCase.endsWith(".xls") || filePathLowCase.endsWith(".xlsx")) {
                    } else {
                        return null
                    }
                }

                TYPE_PPT_TEXT -> {
                    if (filePathLowCase.endsWith(".ppt") || filePathLowCase.endsWith(".pptx")) {
                    } else {
                        return null
                    }
                }

                TYPE_TXT_TEXT -> {
                    if (filePathLowCase.endsWith(".txt")) {
                    } else {
                        return null
                    }
                }

                TYPE_ALL_WENBEN_TEXT -> {
                    if (filePathLowCase.endsWith(".doc") || filePathLowCase.endsWith(".docx") || filePathLowCase.endsWith(
                            ".pdf"
                        ) || filePathLowCase.endsWith(
                            ".xls"
                        ) || filePathLowCase.endsWith(".xlsx") || filePathLowCase.endsWith(".ppt") || filePathLowCase.endsWith(
                            ".pptx"
                        ) || filePathLowCase.endsWith(".txt")
                    ) {
                        fileEntity.fileClass = ItemClassType.DOCUMENTS
                    } else {
                        return null
                    }
                }

                TYPE_COMPRESS_TEXT -> {
                    if (filePathLowCase.endsWith(".zip") && filePathLowCase.endsWith(".rar") || filePathLowCase.endsWith(
                            ".7z"
                        )
                    ) {
                    } else {
                        return null
                    }
                }

                else -> {
                    return null
                }
            }
            fileEntity.dirTypeStr = getDirTypeStrByPath(paramFile.absolutePath)
            fileEntity.filePath = paramFile.absolutePath
            fileEntity.fileName = paramFile.name
            fileEntity.fileType = type
            fileEntity.fileRealType = fileType
            fileEntity.fileLastModifiedTime = getFileLastModifiedTime(paramFile)
            fileEntity.fileLastModifiedTimeMils = paramFile.lastModified()
            fileEntity.fileSizeStr = FileUtils.getSize(paramFile)
            fileEntity.fileSizeLong = FileUtils.getLength(paramFile)
            return fileEntity
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        }
    }


    //一次扫描 将所有分类筛出来
    private fun findSingleFileUpdateAllTypeUi(paramFile: File, type: String): FileEntity? {
        try {
            val fileEntity = FileEntity(UI_TYPE_MAIN)
            val filePathLowCase = paramFile.absolutePath.lowercase(Locale.getDefault())
            val fileType: String = CheckFileTypeUtil.getFileType(paramFile.absolutePath).toString()

            if (filePathLowCase.endsWith(".bmp") || filePathLowCase.endsWith(".jpg") || filePathLowCase.endsWith(
                    ".png"
                ) || filePathLowCase.endsWith(
                    ".tif"
                ) || filePathLowCase.endsWith(".gif") || filePathLowCase.endsWith(".webp") || fileType.equals(
                    "bmp",
                    ignoreCase = true
                ) || fileType.equals("jpg", ignoreCase = true) || fileType.equals(
                    "png",
                    ignoreCase = true
                ) || fileType.equals("tif", ignoreCase = true) || fileType.equals(
                    "gif",
                    ignoreCase = true
                ) || fileType.equals("webp", ignoreCase = true)
            ) {
                fileEntity.fileClass = ItemClassType.PHOTOS
            }

            if (filePathLowCase.endsWith(".mp4") || filePathLowCase.endsWith(".avi") || filePathLowCase.endsWith(
                    ".3gp"
                ) || filePathLowCase.endsWith(
                    ".wmv"
                ) || filePathLowCase.endsWith(".flv") || filePathLowCase.endsWith(".rmvb") || filePathLowCase.endsWith(
                    ".mov"
                )
                || fileType.equals("flv", ignoreCase = true) || fileType.equals(
                    "wmv",
                    ignoreCase = true
                ) || fileType.equals("3gp", ignoreCase = true) || fileType.equals(
                    "avi",
                    ignoreCase = true
                ) || fileType.equals("mp4", ignoreCase = true) || fileType.equals(
                    "rmvb",
                    ignoreCase = true
                ) || fileType.equals(
                    "mov",
                    ignoreCase = true
                )
            ) {
                fileEntity.fileClass = ItemClassType.VIDEOS
            }

            if (filePathLowCase.endsWith(".mp3") || filePathLowCase.endsWith(".amr") || filePathLowCase.endsWith(
                    ".m4a"
                ) || filePathLowCase.endsWith(
                    ".wav"
                ) || filePathLowCase.endsWith(".aac") || filePathLowCase.endsWith(".ogg") || fileType.equals(
                    "mp3",
                    ignoreCase = true
                ) || fileType.equals("amr", ignoreCase = true) || fileType.equals(
                    "m4a",
                    ignoreCase = true
                ) || fileType.equals("wav", ignoreCase = true) || fileType.equals(
                    "aac",
                    ignoreCase = true
                ) || fileType.equals("ogg", ignoreCase = true)
            ) {
                fileEntity.fileClass = ItemClassType.MUSIC
            }

            if (filePathLowCase.endsWith(".doc") || filePathLowCase.endsWith(".docx") || filePathLowCase.endsWith(
                    ".pdf"
                ) || filePathLowCase.endsWith(
                    ".xls"
                ) || filePathLowCase.endsWith(".xlsx") || filePathLowCase.endsWith(".ppt") || filePathLowCase.endsWith(
                    ".pptx"
                ) || filePathLowCase.endsWith(".txt")
            ) {
                fileEntity.fileClass = ItemClassType.DOCUMENTS
            }

            fileEntity.dirTypeStr = getDirTypeStrByPath(paramFile.absolutePath)
            fileEntity.filePath = paramFile.absolutePath
            fileEntity.fileName = paramFile.name
            fileEntity.fileType = type
            fileEntity.fileRealType = fileType
            fileEntity.fileLastModifiedTime = getFileLastModifiedTime(paramFile)
            fileEntity.fileLastModifiedTimeMils = paramFile.lastModified()
            fileEntity.fileSizeStr = FileUtils.getSize(paramFile)
            fileEntity.fileSizeLong = FileUtils.getLength(paramFile)
            return fileEntity
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        }
    }


    private fun getSingleFileByDocumentFileAllType(
        file: DocumentFile,
        type: String
    ): FileEntity? {

        file.type?.let { fileType ->
            if (fileType.contains("image")) {
                val fileEntity = FileEntity(UI_TYPE_MAIN)
                //表示是图片文件，则做保存
                fileEntity.fileClass = ItemClassType.PHOTOS
                fileEntity.fileName = file.name
                fileEntity.fileType = type
                fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                    file.lastModified(),
                    SimpleDateFormat("dd/MM/yyyy")
                )
                fileEntity.fileLastModifiedTimeMils = file.lastModified()
                fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                fileEntity.fileSizeLong = file.length()
                fileEntity.fileRealType = "jpg"
                fileEntity.isDataFile = true
                fileEntity.dirTypeStr = "data"
                fileEntity.isDocumentFile = true
                fileEntity.uriStr = file.uri.toString()
                return fileEntity
            }

            if (fileType.contains("video")) {
                val fileEntity = FileEntity(UI_TYPE_MAIN)
                fileEntity.fileClass = ItemClassType.VIDEOS
                fileEntity.fileName = file.name
                fileEntity.fileType = type
                fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                    file.lastModified(),
                    SimpleDateFormat("dd/MM/yyyy")
                )
                fileEntity.fileLastModifiedTimeMils = file.lastModified()
                fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                fileEntity.fileSizeLong = file.length()
                fileEntity.fileRealType = "mp4"
                fileEntity.isDataFile = true
                fileEntity.dirTypeStr = "data"
                fileEntity.isDocumentFile = true
                fileEntity.uriStr = file.uri.toString()
                return fileEntity
            }


            if (fileType.contains("audio")) {
                val fileEntity = FileEntity(UI_TYPE_MAIN)
                fileEntity.fileClass = ItemClassType.MUSIC
                fileEntity.fileName = file.name
                fileEntity.fileType = type
                fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                    file.lastModified(),
                    SimpleDateFormat("dd/MM/yyyy")
                )
                fileEntity.fileLastModifiedTimeMils = file.lastModified()
                fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                fileEntity.fileSizeLong = file.length()
                fileEntity.fileRealType = "mp3"
                fileEntity.isDataFile = true
                fileEntity.dirTypeStr = "data"
                fileEntity.isDocumentFile = true
                fileEntity.uriStr = file.uri.toString()
                return fileEntity
            }


            if (fileType.equals("application/msword") || fileType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document") || fileType.equals(
                    "application/pdf"
                ) || fileType.equals("application/vnd.ms-excel") || fileType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") || fileType.equals(
                    "application/vnd.ms-powerpoint"
                ) || fileType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation") || fileType.equals(
                    "text/plain"
                )
            ) {
                val fileEntity = FileEntity(UI_TYPE_MAIN)
                fileEntity.fileClass = ItemClassType.DOCUMENTS
                fileEntity.fileName = file.name
                fileEntity.fileType = type
                fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                    file.lastModified(),
                    SimpleDateFormat("dd/MM/yyyy")
                )
                fileEntity.fileLastModifiedTimeMils = file.lastModified()
                fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                fileEntity.fileSizeLong = file.length()
                fileEntity.fileRealType =
                    when (fileType) {
                        "application/msword" -> {
                            "doc"
                        }

                        "application/vnd.openxmlformats-officedocument.wordprocessingml.document" -> {
                            "docx"
                        }

                        "application/pdf" -> {
                            "pdf"
                        }

                        "application/vnd.ms-excel" -> {
                            "xls"
                        }

                        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" -> {
                            "xlsx"
                        }

                        "application/vnd.ms-powerpoint" -> {
                            "ppt"
                        }

                        "application/vnd.openxmlformats-officedocument.presentationml.presentation" -> {
                            "pptx"
                        }

                        "text/plain" -> {
                            "txt"
                        }

                        else -> {
                            ""
                        }
                    }
                fileEntity.isDataFile = true
                fileEntity.dirTypeStr = "data"
                fileEntity.isDocumentFile = true
                fileEntity.uriStr = file.uri.toString()
                return fileEntity
            }
        }
        return null
    }



    private fun getFileFromDirByDocumentFile(
        documentFile: DocumentFile?,
        type: String
    ) {
        //遍历DocumentFile，但是要避开本app的缓存目录，不然会出现很多重复图片
        val files = documentFile?.listFiles()
        files?.let {
            for (file in files) {
                if (file.uri.path?.contains(context.packageName) == true) {
                    continue
                }
                //返回当前正在扫描的文件路径
                pathTextViewModel?.setData(file.uri.path ?: "")

                if (file.isDirectory)//如果是目录则重复本方法往目录下执行。
                    getFileFromDirByDocumentFile(file, type)
                else {//如果是文件则判断文件类型
                    try {
//                        val fileEntity = getSingleFileByDocumentFile(file, type) ?: continue
                        val fileEntity = getSingleFileByDocumentFileAllType(file, type) ?: continue
                        //文件获取成功提醒线程更新
                        fileScanViewModel?.setData(fileEntity)
                    } catch (e: Exception) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    private fun getSingleFileByDocumentFile(
        file: DocumentFile,
        type: String
    ): FileEntity? {
        file.type?.let { fileType ->
            when (type) {
                TYPE_IMAGE_TEXT -> {
                    if (fileType.contains("image")) {
                        val fileEntity = FileEntity(UI_TYPE_MAIN)
                        //表示是图片文件，则做保存
                        fileEntity.fileClass = ItemClassType.PHOTOS
                        fileEntity.fileName = file.name
                        fileEntity.fileType = type
                        fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                            file.lastModified(),
                            SimpleDateFormat("dd/MM/yyyy")
                        )
                        fileEntity.fileLastModifiedTimeMils = file.lastModified()
                        fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                        fileEntity.fileSizeLong = file.length()
                        fileEntity.fileRealType = "jpg"
                        fileEntity.isDataFile = true
                        fileEntity.dirTypeStr = "data"
                        fileEntity.isDocumentFile = true
                        fileEntity.uriStr = file.uri.toString()
                        return fileEntity
                    }
                }

                TYPE_VIDEO_TEXT -> {
                    if (fileType.contains("video")) {
                        val fileEntity = FileEntity(UI_TYPE_MAIN)
                        fileEntity.fileClass = ItemClassType.VIDEOS
                        fileEntity.fileName = file.name
                        fileEntity.fileType = type
                        fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                            file.lastModified(),
                            SimpleDateFormat("dd/MM/yyyy")
                        )
                        fileEntity.fileLastModifiedTimeMils = file.lastModified()
                        fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                        fileEntity.fileSizeLong = file.length()
                        fileEntity.fileRealType = "mp4"
                        fileEntity.isDataFile = true
                        fileEntity.dirTypeStr = "data"
                        fileEntity.isDocumentFile = true
                        fileEntity.uriStr = file.uri.toString()
                        return fileEntity
                    }
                }

                TYPE_AUDIO_TEXT -> {
                    if (fileType.contains("audio")) {
                        val fileEntity = FileEntity(UI_TYPE_MAIN)
                        fileEntity.fileClass = ItemClassType.MUSIC
                        fileEntity.fileName = file.name
                        fileEntity.fileType = type
                        fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                            file.lastModified(),
                            SimpleDateFormat("dd/MM/yyyy")
                        )
                        fileEntity.fileLastModifiedTimeMils = file.lastModified()
                        fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                        fileEntity.fileSizeLong = file.length()
                        fileEntity.fileRealType = "mp3"
                        fileEntity.isDataFile = true
                        fileEntity.dirTypeStr = "data"
                        fileEntity.isDocumentFile = true
                        fileEntity.uriStr = file.uri.toString()
                        return fileEntity
                    }
                }

                TYPE_DOC_TEXT -> {
                    if (fileType.equals("application/msword") || fileType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
                        val fileEntity = FileEntity(UI_TYPE_MAIN)
                        fileEntity.fileName = file.name
                        fileEntity.fileType = type
                        fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                            file.lastModified(),
                            SimpleDateFormat("dd/MM/yyyy")
                        )
                        fileEntity.fileLastModifiedTimeMils = file.lastModified()
                        fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                        fileEntity.fileSizeLong = file.length()
                        if (fileType.equals("application/msword"))
                            fileEntity.fileRealType = "doc"
                        else
                            fileEntity.fileRealType = "docx"
                        fileEntity.isDataFile = true
                        fileEntity.dirTypeStr = "data"
                        fileEntity.isDocumentFile = true
                        fileEntity.uriStr = file.uri.toString()
                        return fileEntity
                    }
                }

                TYPE_PDF_TEXT -> {
                    if (fileType.equals("application/pdf")) {
                        val fileEntity = FileEntity(UI_TYPE_MAIN)
                        fileEntity.fileName = file.name
                        fileEntity.fileType = type
                        fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                            file.lastModified(),
                            SimpleDateFormat("dd/MM/yyyy")
                        )
                        fileEntity.fileLastModifiedTimeMils = file.lastModified()
                        fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                        fileEntity.fileSizeLong = file.length()
                        if (fileType.equals("application/pdf"))
                            fileEntity.fileRealType = "pdf"
                        fileEntity.isDataFile = true
                        fileEntity.dirTypeStr = "data"
                        fileEntity.isDocumentFile = true
                        fileEntity.uriStr = file.uri.toString()
                        return fileEntity
                    }
                }

                TYPE_XLS_TEXT -> {
                    if (fileType.equals("application/vnd.ms-excel") || fileType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
                        val fileEntity = FileEntity(UI_TYPE_MAIN)
                        fileEntity.fileName = file.name
                        fileEntity.fileType = type
                        fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                            file.lastModified(),
                            SimpleDateFormat("dd/MM/yyyy")
                        )
                        fileEntity.fileLastModifiedTimeMils = file.lastModified()
                        fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                        fileEntity.fileSizeLong = file.length()
                        if (fileType.equals("application/vnd.ms-excel"))
                            fileEntity.fileRealType = "xls"
                        else
                            fileEntity.fileRealType = "xlsx"
                        fileEntity.isDataFile = true
                        fileEntity.dirTypeStr = "data"
                        fileEntity.isDocumentFile = true
                        fileEntity.uriStr = file.uri.toString()
                        return fileEntity
                    }
                }

                TYPE_PPT_TEXT -> {
                    if (fileType.equals("application/vnd.ms-powerpoint") || fileType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation")) {
                        val fileEntity = FileEntity(UI_TYPE_MAIN)
                        fileEntity.fileName = file.name
                        fileEntity.fileType = type
                        fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                            file.lastModified(),
                            SimpleDateFormat("dd/MM/yyyy")
                        )
                        fileEntity.fileLastModifiedTimeMils = file.lastModified()
                        fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                        fileEntity.fileSizeLong = file.length()
                        if (fileType.equals("application/vnd.ms-powerpoint"))
                            fileEntity.fileRealType = "ppt"
                        else
                            fileEntity.fileRealType = "pptx"
                        fileEntity.isDataFile = true
                        fileEntity.dirTypeStr = "data"
                        fileEntity.isDocumentFile = true
                        fileEntity.uriStr = file.uri.toString()
                        return fileEntity
                    }
                }

                TYPE_TXT_TEXT -> {
                    if (fileType.equals("text/plain")) {
                        val fileEntity = FileEntity(UI_TYPE_MAIN)
                        fileEntity.fileName = file.name
                        fileEntity.fileType = type
                        fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                            file.lastModified(),
                            SimpleDateFormat("dd/MM/yyyy")
                        )
                        fileEntity.fileLastModifiedTimeMils = file.lastModified()
                        fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                        fileEntity.fileSizeLong = file.length()
                        fileEntity.fileRealType = "txt"
                        fileEntity.isDataFile = true
                        fileEntity.dirTypeStr = "data"
                        fileEntity.isDocumentFile = true
                        fileEntity.uriStr = file.uri.toString()
                        return fileEntity
                    }
                }

                TYPE_ALL_WENBEN_TEXT -> {
                    if (fileType.equals("application/msword") || fileType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document") || fileType.equals(
                            "application/pdf"
                        ) || fileType.equals("application/vnd.ms-excel") || fileType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") || fileType.equals(
                            "application/vnd.ms-powerpoint"
                        ) || fileType.equals("application/vnd.openxmlformats-officedocument.presentationml.presentation") || fileType.equals(
                            "text/plain"
                        )
                    ) {
                        val fileEntity = FileEntity(UI_TYPE_MAIN)
                        fileEntity.fileClass = ItemClassType.DOCUMENTS
                        fileEntity.fileName = file.name
                        fileEntity.fileType = type
                        fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                            file.lastModified(),
                            SimpleDateFormat("dd/MM/yyyy")
                        )
                        fileEntity.fileLastModifiedTimeMils = file.lastModified()
                        fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                        fileEntity.fileSizeLong = file.length()
                        fileEntity.fileRealType =
                            when (fileType) {
                                "application/msword" -> {
                                    "doc"
                                }

                                "application/vnd.openxmlformats-officedocument.wordprocessingml.document" -> {
                                    "docx"
                                }

                                "application/pdf" -> {
                                    "pdf"
                                }

                                "application/vnd.ms-excel" -> {
                                    "xls"
                                }

                                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" -> {
                                    "xlsx"
                                }

                                "application/vnd.ms-powerpoint" -> {
                                    "ppt"
                                }

                                "application/vnd.openxmlformats-officedocument.presentationml.presentation" -> {
                                    "pptx"
                                }

                                "text/plain" -> {
                                    "txt"
                                }

                                else -> {
                                    ""
                                }
                            }
                        fileEntity.isDataFile = true
                        fileEntity.dirTypeStr = "data"
                        fileEntity.isDocumentFile = true
                        fileEntity.uriStr = file.uri.toString()
                        return fileEntity
                    }
                }

                TYPE_COMPRESS_TEXT -> {
                    if (fileType.endsWith(".zip") || fileType.endsWith(".rar") || fileType.endsWith(
                            ".7z"
                        )
                    ) {
                        val fileEntity = FileEntity(UI_TYPE_MAIN)
                        fileEntity.fileName = file.name
                        fileEntity.fileType = type
                        fileEntity.fileLastModifiedTime = TimeUtils.millis2String(
                            file.lastModified(),
                            SimpleDateFormat("dd/MM/yyyy")
                        )
                        fileEntity.fileLastModifiedTimeMils = file.lastModified()
                        fileEntity.fileSizeStr = ConvertUtils.byte2FitMemorySize(file.length())
                        fileEntity.fileSizeLong = file.length()
                        fileEntity.fileRealType = "rar"
                        fileEntity.isDataFile = true
                        fileEntity.dirTypeStr = "data"
                        fileEntity.isDocumentFile = true
                        fileEntity.uriStr = file.uri.toString()
                        return fileEntity
                    }
                }

                else -> {

                }
            }
        }
        return null
    }

    fun destroy() {
        pathTextViewModel = null
        fileScanViewModel = null
        mainJob?.cancel()
        mainJob = null
    }

    private fun getFileLastModifiedTime(paramFile: File): String? {
        val calendar: Calendar = Calendar.getInstance()
        val l = paramFile.lastModified()
        val simpleDateFormat = SimpleDateFormat("dd/MM/yyyy")
        calendar.timeInMillis = l
        return simpleDateFormat.format(calendar.time)
    }

    private fun getDirTypeStrByPath(path: String): String {
        return if (!path.contains("/"))
            "other"
        else {
            val data =
                path.split("/")
            val str = data[data.size - 2]
            str
        }
    }

}

//TODO
const val UI_TYPE_MAIN :Int = 0

class FileEntity(private val itemType: Int = 0) : Serializable {
    var fileClass : ItemClassType = ItemClassType.ALL
    var fileLastModifiedTime: String? = null//文件上次修改时间的转换文案
    var fileLastModifiedTimeMils: Long? = null//文件上次修改时间的毫秒
    var fileName: String? = null//文件名
    var filePath: String? = null//文件路径
    var fileRealType: String? = null//文件真实类型
    var fileSizeStr: String? = null//文件大小的转换文案
    var fileSizeLong: Long = 0//文件大小的字节长度
    var fileType: String? = null//文件类型-Utils的参数
    var isDataFile = false//是否是android/data中的文件
    var isCheck = false//是否被选中
    var bitmap: Bitmap? = null//当前图片的bitmap文件
    var recoverFilePath: String? = null
    var newFileName: String? = null//处理后的文件名
    var dirTypeStr = ""
    var durationStr = "" //视频文件持续时长的格式化字符串
    var duration: Long? = null //视频文件持续时长
    var isDocumentFile = false //是否是通过documentfile方式获得的文件
    var uriStr:String? = null //uri.toString后的数据，通过documentfile方式获得的文件必传
    override fun toString(): String {
        return "FileEntity(itemType=$itemType, fileLastModifiedTime=$fileLastModifiedTime, fileLastModifiedTimeMils=$fileLastModifiedTimeMils, fileName=$fileName, filePath=$filePath, fileRealType=$fileRealType, fileSizeStr=$fileSizeStr, fileSizeLong=$fileSizeLong, fileType=$fileType, isDataFile=$isDataFile, isCheck=$isCheck, bitmap=$bitmap, recoverFilePath=$recoverFilePath, newFileName=$newFileName, dirTypeStr='$dirTypeStr')"
    }
}


class FileTypeEntity : Serializable {
    var key: String? = null
    var value: String? = null
}


enum class ItemClassType {
    PHOTOS,
    VIDEOS,
    MUSIC,
    DOCUMENTS,
    ALL
}

object FileScanUtils {

    /**
     * 判断是否有android/data文件夹权限
     */
    fun isGrantAndroidDataDirPermission(): Boolean {
        //如果当前小于android11就默认获取成功吧，因为android11以下不需要获取data文件夹权限就可以直接访问
        if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
            return true
        }
        val uri =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU){//Android13及以上的data文件夹uri有所变化，所以需要分开处理
                "content://com.android.externalstorage.documents/tree/primary%3AA%E2%80%8Bndroid%2Fdata"
//        "content://com.android.externalstorage.documents/tree/primary%3AA%E2%80%8Bndroid%2Fdata/document/primary%3AA%E2%80%8Bndroid%2Fdata"
            }else{
                "content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata"
//        "content://com.android.externalstorage.documents/tree/primary%3AAndroid%2Fdata/document/primary%3AAndroid%2Fdata"
            }
        val uriPermissionList = Utils.getApp().contentResolver.persistedUriPermissions
        for (persistedUriPermission in uriPermissionList) {
            if (persistedUriPermission.isReadPermission && persistedUriPermission.uri.toString() == uri) {
                return true
            }
        }
        return false
    }
}


object CheckFileTypeUtil {
    private val FILE_TYPE_ENTITY_LIST: MutableList<FileTypeEntity?>

    private val FILE_TYPE_MAP: HashMap<String, String>

    init {
        val hashMap = HashMap<String, String>()
        FILE_TYPE_MAP = hashMap
        val arrayList: ArrayList<FileTypeEntity?> = ArrayList()
        FILE_TYPE_ENTITY_LIST = arrayList
        hashMap["FFD8FF"] = "jpg"
        hashMap["89504E"] = "png"
        hashMap["47494638"] = "gif"
        hashMap["1A45DFA3934282886D6174726F736B61"] = "mkv"
        hashMap["00000020667479704D34412000000000"] = "m4a"
        hashMap["000000146674797069736F6D"] = "mp4"
        hashMap["00000018667479706D70343200000000"] = "mp4" //00000018667479706D70343200000000
        hashMap["000000186674797033677035"] = "mp4" //00000018667479706D70343200000000
        hashMap["0000001C66747970"] = "mp4"
        hashMap["255044"] = "pdf"
        hashMap["D0CF11E0"] = "doc"
        hashMap["504B0304"] = "docx"
        hashMap["D0CF11E0"] = "xls"
        hashMap["504B0304"] = "xlsx"
        hashMap["D0CF11E0"] = "ppt"
        hashMap["504b0304"] = "pptx"
        hashMap["49492A"] = "tif"
        hashMap["424d22"] = "bmp"
        hashMap["424d82"] = "bmp"
        hashMap["424d8e"] = "bmp"
        hashMap["414331"] = "dwg"
        hashMap["3C2144"] = "htm"
        hashMap["3C21444F4354"] = "html"
        hashMap["48544d"] = "css"
        hashMap["696b2e"] = "js"
        hashMap["7B5C72"] = "rtf"
        hashMap["384250"] = "psd"
        hashMap["00000100"] = "ico"
        hashMap["44656C69766572792D646174653A"] = "eml"
        hashMap["5374616E64617264204A"] = "mdb"
        hashMap["252150532D41646F6265"] = "ps"
        hashMap["25215053"] = "eps"
        hashMap["2E524D46"] = "rmvb"
        hashMap["2E524D"] = "rm"
        hashMap["464C5601"] = "flv"
        hashMap["494433"] = "mp3"
        hashMap["000001BA"] = "mpg"
        hashMap["000001B3"] = "mpg"
        hashMap["3026b2"] = "wmv"
        hashMap["3026B2758E66CF11"] = "asf"
        hashMap["57415645"] = "wav"
        hashMap["41564920"] = "avi"
        hashMap["4D546864"] = "mid"
        hashMap["504B3030504B0304"] = "zip"
        hashMap["52617221"] = "rar"
        hashMap["235468"] = "ini"
        hashMap["4d5a90"] = "exe"
        hashMap["3c2540"] = "jsp"
        hashMap["4d616e"] = "mf"
        hashMap["3C3F786D6C"] = "xml"
        hashMap["494e53"] = "sql"
        hashMap["706163"] = "java"
        hashMap["406563"] = "bat"
        hashMap["1f8b"] = "gz"
        hashMap["6c6f67"] = "properties"
        hashMap["cafeba"] = "class"
        hashMap["49545346"] = "chm"
        hashMap["040000"] = "mxp"
        hashMap["643130"] = "torrent"
        hashMap["6D6F6F76"] = "mov"
        hashMap["FF575043"] = "wpd"
        hashMap["CFAD12FEC5FD746F"] = "dbx"
        hashMap["2142444E"] = "pst"
        hashMap["AC9EBD8F"] = "qdf"
        hashMap["E3828596"] = "pwl"
        hashMap["2E7261FD"] = "ram"
        arrayList.clear()
        for ((key, value) in hashMap) {
            val str1 = key as String
            val str2 = value as String
            val fileTypeEntity = FileTypeEntity()
            fileTypeEntity.key = str1
            fileTypeEntity.value = str2
            FILE_TYPE_ENTITY_LIST.add(fileTypeEntity)
        }
    }

    private fun bytesToHexString(paramArrayOfbyte: ByteArray?): String? {
        val stringBuilder = StringBuilder()
        if (paramArrayOfbyte == null || paramArrayOfbyte.size <= 0) return null
        for (i in paramArrayOfbyte.indices) {
            val str = Integer.toHexString(paramArrayOfbyte[i].toInt() and 0xFF)
                .uppercase(Locale.getDefault())
            if (str.length < 2) stringBuilder.append(0)
            stringBuilder.append(str)
        }
        return stringBuilder.toString()
    }

    fun getFileHeader(paramString: String?): String? {
        var paramString = paramString
        val str2: String? = null
        var str1 = str2
        try {
            val fileInputStream = FileInputStream(paramString)
            try {
                val arrayOfByte = ByteArray(16)
                fileInputStream.read(arrayOfByte, 0, 16)
                val str = bytesToHexString(arrayOfByte)
                str1 = str
                return str
            } finally {
                fileInputStream.close()
                paramString = null
            }
        } catch (iOException: IOException) {
            iOException.printStackTrace()
            return str1
        }
    }

    fun getFileType(paramString: String?): String? {
        var paramString = paramString
        paramString = getFileHeader(paramString)
        if (!TextUtils.isEmpty(paramString)) {
            var i = 0
            while (true) {
                val list: List<FileTypeEntity?> = FILE_TYPE_ENTITY_LIST
                if (i < list.size) {
                    val nowTypeHeader = list[i]!!.key!!.uppercase(Locale.getDefault())
                    if (paramString!!.length >= nowTypeHeader.length) {
                        //被识别的文件头长度大于当前循环类型的文件头长度，那么就判断被识别的文件头初始是否与当前循环类型文件头一样，如果一样则表示是指定类型文件
                        if (paramString.startsWith(nowTypeHeader)) {
                            return FILE_TYPE_MAP[list[i]!!.key]
                        }
                    } else {
                        //被识别的文件头长度小于当前循环类型的文件头长度，那么就判断当前循环类型的文件头初始是否与被识别文件头一样，如果一样则表示是指定类型文件
                        if (nowTypeHeader.startsWith(paramString)) {
                            return FILE_TYPE_MAP[list[i]!!.key]
                        }
                    }
                    //                    if (paramString.contains(list.get(i).getKey().toUpperCase()) || list.get(i).getKey().toUpperCase().contains(paramString))
//                        return FILE_TYPE_MAP.get(list.get(i).getKey());
                    i++
                    continue
                }
                break
            }
        }
        return ""
    }

    @JvmStatic
    fun main(paramArrayOfString: Array<String>) {
        val str = getFileType("D:\\picture.jpg")
        val printStream = System.out
        val stringBuilder = StringBuilder()
        stringBuilder.append("fileType = ")
        stringBuilder.append(str)
        printStream.println(stringBuilder.toString())
    }
}
